var from = 'text';
var gen_compressed = true;
var gen_eckey = null;
var gen_pt = null;
var gen_ps_reset = false;
var TIMEOUT = 600;
var timeout = null;

var PUBLIC_KEY_VERSION = 0;
var PRIVATE_KEY_VERSION = 0x80;
var ADDRESS_URL_PREFIX = l("blockinfo_url");
var WORD_NUM = 100;
var al = 10;
//var payload = '';

function round_word(n){
	var keyword = '';
	for(var i = 0;i<n;i++){
		eval( "var word=" +  '"\\u' + (Math.round(Math.random() * 20901) + 19968).toString(16)+'"');
		keyword += word;
	}
	return keyword;
}


function pad(str, len, ch) {
	padding = '';
	for (var i = 0; i < len - str.length; i++) {
		padding += ch;
	}
	return padding + str;
}


function getEncoded(pt, compressed) {
   var x = pt.getX().toBigInteger();
   var y = pt.getY().toBigInteger();
   var enc = integerToBytes(x, 32);
   if (compressed) {
	 if (y.isEven()) {
	   enc.unshift(0x02);
	 } else {
	   enc.unshift(0x03);
	 }
   } else {
	 enc.unshift(0x04);
	 enc = enc.concat(integerToBytes(y, 32));
   }
   return enc;
}


// stringToBytes, exception-safe
function stringToBytes(str) {
  try {
	var bytes = Crypto.charenc.UTF8.stringToBytes(str);
  } catch (err) {
	var bytes = [];
	for (var i = 0; i < str.length; ++i)
	   bytes.push(str.charCodeAt(i));
  }
  return bytes;
}

// bytesToString, exception-safe
function bytesToString(bytes) {
  try {
	var str = Crypto.charenc.UTF8.bytesToString(bytes);
  } catch (err) {
	var str = '';
	for (var i = 0; i < bytes.length; ++i)
		str += String.fromCharCode(bytes[i]);
  }
  return str;
}


function isHex(str) {
	return !/[^0123456789abcdef]+/i.test(str);
}

function isBase58(str) {
	return !/[^123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+/.test(str);
}

function isBase64(str) {
	return !/[^ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=]+/.test(str) && (str.length % 4) == 0;
}

function isBin(str) {
  return !/[^01 \r\n]+/i.test(str);
}

function isDec(str) {
  return !/[^0123456789]+/i.test(str);
}

function issubset(a, ssv) {
	var b = ssv.trim().split(' ');
	for (var i = 0; i < b.length; i++) {
		if (a.indexOf(b[i].toLowerCase()) == -1 
			&& a.indexOf(b[i].toUpperCase()) == -1)
		return false;
	}
	return true;
}

function isEasy16(str) {
  return !/[^asdfghjkwertuion \r\n]+/i.test(str);
}

function autodetect(str) {
	var enc = [];
	var bstr = str.replace(/[ :,\n]+/g,'').trim();
	if ( isBin(bstr) )
		enc.push('bin');
	if (isDec(bstr) )
		enc.push('dec');
	if (isHex(bstr))
		enc.push('hex');
	if (isBase58(bstr)) {
		// push base58check first (higher priority)
		try {
			var res = parseBase58Check(bstr);
			enc.push('base58check');
		} catch (err) {};
	}
	if (issubset(mn_words, str))
		enc.push('mnemonic');
	if (issubset(rfc1751_wordlist, str)) 
		enc.push('rfc1751');
	if (isEasy16(bstr))
	  enc.push('easy16');
	if (isBase64(bstr))
		enc.push('base64');
	if (str.length > 0) {
		enc.push('text');
		enc.push('rot13');
	}
	if (isBase58(bstr)) {
	  // arbitrary text should have higher priority than base58
	  enc.push('base58');
	}
	return enc;
}

function update_toolbar(enc_list) {
	var reselect = false;

	$.each($('#enc_from').children(), function() {
		var enc = $(this).children().attr('id').substring(5);
		var disabled = (enc_list && enc_list.indexOf(enc) == -1);
		if (disabled && $(this).hasClass('active')) {
			$(this).removeClass('active');
			reselect = true;
		}
		$(this).attr('disabled', disabled);
	});

	if (enc_list && enc_list.length > 0) {
		if (reselect || from=='') {
		  from = enc_list[0];
		  $('#from_' + from).click();
		}
	}
}

function rot13(str) {
	return str.replace(/[a-zA-Z]/g, function(c) {
	  return String.fromCharCode((c <= 'Z' ? 90 : 122) >= (c = c.charCodeAt(0) + 13) ? c : c - 26);
	});
}

function fromEasy16(str) {
  var keys = str.split('\n');
  var res = [];
  for (var i = 0; i < keys.length; i++) {
	var k = keys[i].replace(' ','');
	var raw = Crypto.util.hexToBytes(armory_map(k, armory_f, armory_t));
	data = raw.slice(0, 16);
	res = res.concat(data);
  }
  return res;
}

function toEasy16(bytes) {
	var keys = armory_encode_keys(bytes,[]);
	var lines = keys.split('\n');
	var res = [];
	for (var i in lines) {
	  if (lines[i].trim(' ').split(' ').length==9)
		res.push(lines[i]);
	}
	return res.join('\n');
}

function toBin(bytes)
{
  var arr = [];
  for (var i=0; i<bytes.length;i++)
  {
	var s = (bytes[i]).toString(2);
	arr.push(('0000000' + s).slice(-8));
  }
  return arr.join(' ');
}

function fromBin(str)
{
  var arr = str.split(/[\r\n ]+/);
  var res = [];
  for (var i=0; i<arr.length; i++)
  {
	var bstr = arr[i];
	var s = ('0000000'+bstr).slice(-Math.ceil(bstr.length/8)*8); // needs padding
	var chunks = s.match(/.{1,8}/g);
	 for (var j=0;j<chunks.length;j++)
	  res.push(parseInt(chunks[j], 2));
  }
  return res;
}
function parseBase58Check(address) {
	var bytes = Bitcoin.Base58.decode(address);
	var end = bytes.length - 4;
	var hash = bytes.slice(0, end);
	var checksum = Crypto.SHA256(Crypto.SHA256(hash, {asBytes: true}), {asBytes: true});
	if (checksum[0] != bytes[end] || checksum[1] != bytes[end+1] || checksum[2] != bytes[end+2] || checksum[3] != bytes[end+3]){
		result = {'result':0,'response':'wrong checksum'};
	} else {
		result = {'result':1,'version':hash.shift(),'hash':hash, 'response':'valid checksum'};
	}
	return result;
}
function fromDec(str)
{
	var h = new BigInteger(str).toString(16);
	return Crypto.util.hexToBytes(h.length%2?'0'+h:h);
}

function toDec(bytes)
{
	var h = Crypto.util.bytesToHex(bytes);
	return new BigInteger(h,16).toString(10);
}

function enct(id) {
	return $('#from_'+id).parent().text();
}

function pad_array(bytes, n)
{
  if (n==0) // remove padding
  {
	var res = bytes.slice(0);
	while (res.length>1 && res[0]==0)
	  res.shift();
	return res;
  }

  // align to n bytes
  var len = bytes.length;
  var padding = Math.ceil(len/n)*n - len;
  var res = bytes.slice(0);
  for (i=0;i<padding;i++)
	res.unshift(0);
  return res;
}

function translate(str,from,to) {

	if (str.length == 0) {
		
	  return;
	}

	text = str;

	bytes = stringToBytes(str);

	var type = '';

	if (bytes.length > 0) {
		var bstr = str.replace(/[ :,\n]+/g,'').trim();

		if (from == 'base58check') {
			try {
				var res = parseBase58Check(bstr);
				type = ' ver. 0x' + Crypto.util.bytesToHex([res[0]]);
				bytes = res[1];
			} catch (err) {};
		} else if (from == 'base58') {
			bytes = Bitcoin.Base58.decode(bstr);
		} else if (from == 'hex') {
			bytes = Crypto.util.hexToBytes(bstr.length%2?'0'+bstr:bstr); // needs padding
		} else if (from == 'rfc1751') {
			try { bytes = english_to_key(str); } catch (err) { type = ' ' + err; bytes = []; };
		} else if (from == 'mnemonic') {
			bytes = Crypto.util.hexToBytes(mn_decode(str.trim()));
		} else if (from == 'base64') {
			try { bytes = Crypto.util.base64ToBytes(bstr); } catch (err) {}
		} else if (from == 'rot13') {
			bytes = stringToBytes(rot13(str));
		} else if (from == 'bin') {
			bytes = fromBin(str);
		} else if (from == 'easy16') {
			bytes = fromEasy16(str);
		} else if (from == 'dec') {
			bytes = fromDec(bstr);
		}

		var ver = '';
		if (to == 'base58check') {
		   var addr = new Bitcoin.Address(bytes);
		   addr.version = bytes.length <= 20 ? PUBLIC_KEY_VERSION : PRIVATE_KEY_VERSION;
		   text = addr.toString();
		   ver = ' ver. 0x' + Crypto.util.bytesToHex([addr.version]);
		} else if (to == 'base58') {
			text = Bitcoin.Base58.encode(bytes);
		} else if (to == 'hex') {
			text = Crypto.util.bytesToHex(bytes);
		} else if (to == 'text') {
			text = bytesToString(bytes);
		} else if (to == 'rfc1751') {
			text = key_to_english(pad_array(bytes,8));
		} else if (to == 'mnemonic') {
			text = mn_encode(Crypto.util.bytesToHex(pad_array(bytes,4)));
		} else if (to == 'base64') {
			text = Crypto.util.bytesToBase64(bytes);
		} else if (to == 'rot13') {
			text = rot13(bytesToString(bytes));
		} else if (to == 'bin') {
			text = toBin(bytes);
		} else if (to == 'easy16') {
			text = toEasy16(pad_array(bytes,32));
		} else if (to == 'dec') {
			text = toDec(bytes);
		}
	}
	return text;
}


function generate(){
	keyword = round_word(WORD_NUM);
 	var hash = Crypto.SHA256(keyword, { asBytes: true });
	eckey = new Bitcoin.ECKey(hash);
	gen_eckey = eckey;

	try {
		var curve = getSECCurveByName("secp256k1");
		gen_pt = curve.getG().multiply(eckey.priv);
		gen_eckey.pub = getEncoded(gen_pt, gen_compressed);
		gen_eckey.pubKeyHash = Bitcoin.Util.sha256ripe160(gen_eckey.pub);
		//setErrorState($('#hash'), false);
	} catch (err) {
		console.info(err);
		//setErrorState($('#hash'), true, '无效的保密指数（必须是非零的值）');
		return;
	}
	
	var hash160 = eckey.getPubKeyHash();
	var h160 = Crypto.util.bytesToHex(hash160);
	var addr = new Bitcoin.Address(hash160);
	addr.version = PUBLIC_KEY_VERSION;
	
	var payloads = hash;
	var compressed = gen_compressed;
	if (compressed)
		payloads.push(0x01);

	var sec = new Bitcoin.Address(payloads);
	sec.version = PRIVATE_KEY_VERSION;
	var nowDate = new Date();
	var nowtime = nowDate.getTime()
	var pub = Crypto.util.bytesToHex(getEncoded(gen_pt, compressed));
	var bitJson = '{ "addr":"'+addr+'","priv":"'+sec+'","pub":"'+pub+'" ,"version":"'+addr.version+'" ,"createTime":'+nowtime+'  }'; 
	return bitJson;
}

//test
function listProperties(obj, objName) {
    var result = "";
    for (var i in obj) {
        result += objName + "." + i + "=" + obj[i] + "\n";
    }
    alert(result);
} 


function trim(str){   
    str = str.replace(/^(\s|\u00A0)+/,'');   
    for(var i=str.length-1; i>=0; i--){   
        if(/\S/.test(str.charAt(i))){   
            str = str.substring(0, i+1);   
            break;   
        }   
    }   
    return str;   
}
function getHash(str){
	var hash = Crypto.SHA256(str, { asBytes: true });
	eckey = new Bitcoin.ECKey(hash);
	return eckey.toString();
}
function getrandomkey(){
	var _xsrf = getCookie("_xsrf");
	var randomkey = '';
	$.ajax({
		type: "post", async: false, cache: false, dataType: "text", 
		url: "/payset",
		data: {op:'getrandomkey' ,_xsrf:_xsrf},
		success: function (result) {
			randomkey =  result; 
		},
		error: function () {
		}
	});
	return randomkey;
}
function pwdEncrypt(pwd){
	var data = getrandomkey()
	
	var get_hash = $.parseJSON(data)
	var json_str = '{"pwd":"'+pwd+'"}'
	var str = CryptoJS.AES.encrypt(json_str, get_hash['rnd_key'], { mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Iso10126 });
	str = str.toString();
	return translate(str,'text','mnemonic');
}
function pwdDecrypt(word){
	return translate(word,'mnemonic','text');
}

function bitEncrypt(str,pwd,json){
	var jsonstr = '{ "keys": [';
	if(json){
		try{
			for(var i=0;i<json.keys.length;i++){
				json.keys[i]['version'] = parseInt(json.keys[i]['version'])+1;
				jsonstr = jsonstr + JSON.stringify(json.keys[i])
				if(str!='' || i < (json.keys.length-1)){ 
					jsonstr = jsonstr +',';
				}
			}
		}catch(e){
			return('encrypt_error')
		}
	}
	jsonstr = jsonstr + str; 
	jsonstr = jsonstr + ']}';  
	var encrypted = CryptoJS.AES.encrypt(jsonstr, pwd, { mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Iso10126 });
	return encrypted;
}
function bitDecrypt(payload,pwd){
    try {
        var decrypt = CryptoJS.AES.decrypt(payload, pwd, { mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Iso10126 });
        try{
            $.parseJSON(decrypt.toString(CryptoJS.enc.Utf8));
        }catch(e){
            return 'error';
        }
        
        if(decrypt.toString(CryptoJS.enc.Utf8) == ""){
            return 'error';
        }else{
            return decrypt.toString(CryptoJS.enc.Utf8);
        }

    　} catch(err) {
    //console.log(err)
    　　 return 'error';
    　　}
}



function getCoinSum(tx){
	var sum = 0;
	for(var i= 0;i<tx.length;i++){
		if(tx[i]['v']){
			sum += tx[i]['v']; 
		}
	}

		return sum;

}




